package com.qianfeng.openapi.zuul.filter;

import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.qianfeng.openapi.zuul.exception.ExceptionDict;
import com.qianfeng.openapi.zuul.exception.GatewayException;
import com.qianfeng.openapi.zuul.utils.DateUtils;
import com.qianfeng.openapi.zuul.utils.SysConstant;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 参数校验
 * @Company: 千锋互联
 * @Author: 李丽婷
 * @Date: 2021/1/4
 * @Time: 上午9:26
 */
@Component
public class SysParameterFilter  extends ZuulFilter {
    @Override
    public String filterType() {

        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        //1.请求上下文对象
        RequestContext context = RequestContext.getCurrentContext();
        //2.得到请求对象
        HttpServletRequest request = context.getRequest();
        //3.得到参数
        //4.校验参数
        //4.1 method  调用的api信息
        try {
            validateMethod(request);
            //4.2 appKey   商家的平台的appKey
            validateAppKey(request);
            //4.3 sign   签名  请求url的唯一性
            validateSign(request);
            //4.4 timestamp   时间戳
            validateTimeStamp(request);
            //4.5 token 访问的token
            validateTOKEN(request);
            System.out.println("------>参数校验成功");
        } catch (GatewayException e) {
            context.getResponse().setContentType("application/json;charset=utf-8");//响应内容类型  防止乱码
            context.setSendZuulResponse(false);
            context.setResponseStatusCode(HttpStatus.BAD_REQUEST.value());
            Map<String,Object> map = new HashMap<>();
            map.put("code",e.getCode());//错误码
            map.put("msg",e.getMsg());//错误信息

            String json = JSON.toJSONString(map);

            context.setResponseBody(json);

        }


        return null;
    }

    private void validateMethod(HttpServletRequest request) {
        String method = request.getParameter(SysConstant.METHOD);
        if (StringUtils.isBlank(method)){//null  ""  " "
            throw  new GatewayException(ExceptionDict.ERROR_PARAM,"请确认是否传递了method参数");
        }
    }

    private void validateAppKey(HttpServletRequest request) {
        String method = request.getParameter(SysConstant.APPKEY);
        if (StringUtils.isBlank(method)){//null  ""  " "
            throw  new GatewayException(ExceptionDict.ERROR_PARAM,"请确认是否传递了appKey参数");
        }
    }
    private void validateSign(HttpServletRequest request) {
        String method = request.getParameter(SysConstant.SIGN);
        if (StringUtils.isBlank(method)){//null  ""  " "
            throw  new GatewayException(ExceptionDict.ERROR_PARAM,"请确认是否传递了sign参数");
        }
    }
    private void validateTimeStamp(HttpServletRequest request) {
        String t = request.getParameter(SysConstant.TIMESTAMP);
        //是否传了该参数
        if (StringUtils.isBlank(t)){//null  ""  " "
            throw  new GatewayException(ExceptionDict.ERROR_PARAM,"请确认是否传递了timestamp参数");
        }
        //时间戳校验   请求是否过期  允许客户端和服务端有10分钟误差
        Date clientDate = DateUtils.getDate(t,"yyyy-MM-dd hh:mm:ss");
        if (clientDate==null){
            throw  new GatewayException(ExceptionDict.ERROR_PARAM,"请确认timestamp参数格式是否正确(yyyy-MM-dd hh:mm:ss)");
        }
        //10分钟后的时间
        Date maxDate = DateUtils.addDate(clientDate,1000,Calendar.MINUTE);
        //10分钟前的时间
        Date minDate = DateUtils.addDate(clientDate,-1000,Calendar.MINUTE);
        //如果客户端的时间+10分钟后比系统当前时间还大
        // 或者客户端的时间-10分钟后比系统当前时间还小
        //那么请求非法  过期
        //public static boolean compareTimeStamp(Date visitTime, Date serverTime)
        //开始日期(参数一的时间)小于等于结束日期（参数二的时间）为true,反之False

        if (!DateUtils.compareTimeStamp(maxDate,new Date())
                ||!DateUtils.compareTimeStamp(new Date(),minDate)){
            throw  new GatewayException(ExceptionDict.ERROR_PARAM,"timestamp参数无效，请求过期");
        }

    }
    private void validateTOKEN(HttpServletRequest request) {
        String method = request.getParameter(SysConstant.TOKEN);
        if (StringUtils.isBlank(method)){//null  ""  " "
            throw  new GatewayException(ExceptionDict.ERROR_PARAM,"请确认是否传递了token参数");
        }
    }
}

